/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.iec.edp.caf.commons.utils;

import io.iec.edp.caf.multicontext.context.PlatformApplicationContext;
import io.iec.edp.caf.multicontext.support.LocalThreadModule;
import io.iec.edp.caf.multicontext.support.Module;
import lombok.var;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;


/**
 * @author wangyandong
 * @date 2019/9/20 15:13
 *
 */
//@Component
public class SpringBeanUtils {
    /**
     * Spring应用上下文环境
     */
    private static ApplicationContext applicationContext;

    /**
     * 实现ApplicationContextAware接口的回调方法。设置上下文环境
     *
     * @param applicationContext
     */

    public static void setApplicationContext(ApplicationContext applicationContext) {
        SpringBeanUtils.applicationContext = applicationContext;
    }

    /**
     * @return ApplicationContext
     */
    public static ApplicationContext getApplicationContext() {
        Module module = LocalThreadModule.getModule();
        if (module != null) {
            return module.getContext();
        }

        return applicationContext;
    }

    /**
     * 根据模块名获取模块
     * 因为运行时拿的getApplicationContext永远是platformcontext，所以业务模块里里的bean通过getBeansOfType会出现拿不到的情况（打了@Collect注解的除外）
     * @param moduleName
     * @return
     */
    public static ApplicationContext getApplicationContextByModule(String moduleName){
        ApplicationContext modulecontext = null;
        if(applicationContext instanceof PlatformApplicationContext){
            var modulemanager = ((PlatformApplicationContext)applicationContext).getModuleManager();
            var module = modulemanager.getModule(moduleName);
            modulecontext = module!=null?module.getContext():modulecontext;
        }

        return modulecontext;
    }

    /**
     * 获取对象
     *
     * @param name
     * @return Object
     * @throws BeansException
     */
    public static Object getBean(String name) {
        ApplicationContext applicationContext = getApplicationContext();
        if (applicationContext != null)
            return applicationContext.getBean(name);
        return null;
    }

    /**
     * 获取对象
     *其实getBean也可以拿到，因为getBean是遍历的所有的子模块拿的，理论上这个方法比getBean效率高一些
     * @param name
     * @return Object
     * @throws BeansException
     */
    public static Object getBeanByModule(String name,String moduleName) {
        ApplicationContext applicationContext = getApplicationContextByModule(moduleName);
        if (applicationContext != null)
            return applicationContext.getBean(name);
        return null;
    }

    /**
     * 获取对象通过Class
     *
     * @param requiredType
     * @return Object
     * @throws BeansException
     */
    public static <T> T getBean(Class<T> requiredType) {
        ApplicationContext applicationContext = getApplicationContext();
        if (applicationContext != null)
            return applicationContext.getBean(requiredType);
        return null;
    }

    /**
     * 获取对象通过Class
     *
     * @param requiredType
     * @return Object
     * @throws BeansException
     */
    public static <T> T getBeanByModule(Class<T> requiredType,String moduleName) {
        ApplicationContext applicationContext = getApplicationContextByModule(moduleName);
        if (applicationContext != null)
            return applicationContext.getBean(requiredType);
        return null;
    }

    /**
     * 获取对象通过Class
     *
     * @param name
     * @param requiredType
     * @return Object
     * @throws BeansException
     */
    public static <T> T getBean(String name, Class<T> requiredType) {
        ApplicationContext applicationContext = getApplicationContext();
        if (applicationContext != null)
            return applicationContext.getBean(name, requiredType);
        return null;
    }

    /**
     * 获取对象通过Class
     *
     * @param name
     * @param requiredType
     * @return Object
     * @throws BeansException
     */
    public static <T> T getBeanByModule(String name, Class<T> requiredType,String moduleName) {
        ApplicationContext applicationContext = getApplicationContextByModule(moduleName);
        if (applicationContext != null)
            return applicationContext.getBean(name, requiredType);
        return null;
    }

}
